package com.huaxin.hxjwt.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.huaxin.hxjwt.entity.JwtModel;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.SecretKey;
import java.util.Base64;
import java.util.Date;

/**
 * JWT 工具类
 * 用于生成、解析和验证 JWT Token。
 * 注意：此工具类不依赖 Spring Security 的 SecurityContext。
 */
public class JwtUtils {

    private static final Logger log = LoggerFactory.getLogger(JwtUtils.class);

    // ✅ 1. 密钥现在通过构造函数或配置注入。这里暂时保留，但建议在实际使用时通过 @Value 注入
    // 例如，在 Spring Boot 中，可以在使用它的服务里通过 @Value("${jwt.secret}") 获取
    // 或者将这个类改为 @Component 并使用 @Value
    private static final String SECRET_KEY_BASE64 = "9oHuD5sUWLllNt0VIIzBT3gAk30OQ6UN5ovUoKd5eZdkSEOBYhI9ReeyvLzt6N4ZEO7YmeD4TAboA610A3KXpA==";
    // ✅ 1. 将 Base64 字符串转换为 SecretKey 对象
    private static final SecretKey SECRET_KEY;

    // 静态代码块：在类加载时执行，用于初始化 SECRET_KEY
    static {
        try {
            // a. 将 Base64 字符串解码为原始字节数组
            byte[] keyBytes = Base64.getDecoder().decode(SECRET_KEY_BASE64);
            // b. 使用 JJWT 提供的 Keys 工具类，根据字节数组创建符合 HS512 要求的 SecretKey
            //    Keys.hmacShaKeyFor() 会验证字节数组的长度是否足够 (HS512 需要至少 512 bits / 64 bytes)
            SECRET_KEY = Keys.hmacShaKeyFor(keyBytes);
        } catch (IllegalArgumentException e) {
            // 如果 Base64 解码失败或密钥长度不足，会抛出此异常
            throw new RuntimeException("初始化 JWT 密钥失败。请检查 SECRET_KEY_BASE64 是否是有效的 Base64 字符串且长度足够。", e);
        }
    }

    private static final long EXPIRATION_TIME = 7 * 24 * 60 * 60 * 1000; // 7天

    /**
     * 生成 JWT Token
     */
    public static String generateToken(JwtModel in) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String jwtModelAsString = objectMapper.writeValueAsString(in);
            return Jwts.builder()
                    .setSubject(jwtModelAsString) // 存储用户信息
                    .setIssuedAt(new Date()) // 设置签发时间
                    .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // 设置过期时间
                    .signWith(SECRET_KEY) // 使用密钥进行签名
                    .compact();
        } catch (JsonProcessingException e) {
            log.error("序列化 JwtModel 为 JSON 字符串时发生错误", e); // ✅ 使用日志
            return null; // 或者抛出一个自定义异常
        }
    }

    /**
     * 解析 JWT Token 获取 Claims
     */
    public static Claims parseToken(String token) throws JwtException {
        return Jwts.parserBuilder()
                .setSigningKey(SECRET_KEY)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 验证 Token 是否有效
     */
    public static boolean validateToken(String token) {
        try {
            parseToken(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            log.debug("Token 验证失败: {}", e.getMessage()); // 使用 debug 级别，避免日志过多
            return false;
        }
    }

    /**
     * 从 Token 中解析出 JwtModel 对象
     *
     * @param token JWT Token
     * @return 解析出的 JwtModel
     * @throws Exception 如果解析失败（如 Token 无效、格式错误、JSON 反序列化失败等）
     */
    public static JwtModel getJwtModelFromToken(String token) throws Exception {
        Claims claims = parseToken(token); // 复用 parseToken 的逻辑
        String jwtModelAsString = claims.getSubject();

        if (jwtModelAsString == null || jwtModelAsString.isEmpty()) {
            throw new IllegalArgumentException("Token subject 为空");
        }

        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.readValue(jwtModelAsString, JwtModel.class);
        } catch (JsonProcessingException e) {
            log.error("反序列化 JSON 字符串为 JwtModel 时发生错误", e);
            throw new Exception("Token 数据损坏", e);
        }
    }
}